<template>
  <div class="login_container">
    <!-- v-model：控制对话框显示隐藏，
            这个属性不建议设置到本组件中，
            因为对话框的显示隐藏，可能是由这个组件的父组件，兄弟组件，子组件等来控制，
            所以定义到仓库中是最合适的 
        -->
    <!-- title：对话框左上角标题 -->
    <el-dialog v-model="userStore.visiable" title="用户登录">
      <!-- 对话框身体部分的结构 -->
      <el-row>
        <!-- 左侧结构：手机号码登录、微信扫一扫登录 -->
        <el-col :span="12">
          <div class="login">
            <div v-show="scene == 0">
              <el-form :model="loginParam" :rules="rules" ref="form">
                <el-form-item prop="phone">
                  <el-input
                    placeholder="请输入手机号码"
                    :prefix-icon="User"
                    v-model="loginParam.phone"
                  >
                  </el-input>
                </el-form-item>
                <el-form-item prop="code">
                  <el-input
                    placeholder="请输入手机验证码"
                    :prefix-icon="Lock"
                    v-model="loginParam.code"
                  ></el-input>
                </el-form-item>
                <el-form-item>
                  <el-button :disabled="!isPhone || flag ? true : false" @click="getCode()">
                    <CountDown v-if="flag" v-model="flag" />
                    <span v-else>获取验证码</span>
                  </el-button>
                </el-form-item>
              </el-form>
              <el-button
                style="width: 100%"
                type="primary"
                size="default"
                :disabled="!isPhone || loginParam.code.length < 6 ? true : false"
                @click="login()"
              >
                用户登录
              </el-button>
              <div class="bottom" @click="changeScene">
                <p>微信扫码登录</p>
                <SvgIcon name="weixin" width="32px" height="32px" class="icon"></SvgIcon>
              </div>
            </div>
            <div class="webchat" v-show="scene == 1">
              <!-- 在这个容器当中显示微信扫码登录的页面 -->
              <div id="login_container"></div>
              <div class="phone" @click="handler">
                <p>手机短信验证码登录</p>
                <SvgIcon name="phone" width="32px" height="32px" class="icon"></SvgIcon>
              </div>
            </div>
          </div>
        </el-col>
        <!-- 右侧 -->
        <el-col :span="12">
          <div class="leftContent">
            <div class="top">
              <div class="item">
                <img src="../../assets/images/code_app.png" alt="" />
                <SvgIcon name="weixin" width="16px" height="16px" class="icon"></SvgIcon>
                <p>微信扫一扫关注</p>
                <p>“快速预约挂号”</p>
              </div>
              <div class="item">
                <img src="../../assets/images/code_login_wechat.png" alt="" />
                <SvgIcon name="phone" width="16px" height="16px" class="icon"></SvgIcon>
                <p>扫一扫下载</p>
                <p>“预约挂号”APP</p>
              </div>
            </div>
          </div>
          <p class="tip">尚医通官方指定平台</p>
          <p class="tip">快速挂号，安全放心</p>
        </el-col>
      </el-row>

      <!-- 底部插槽 -->
      <template #footer>
        <el-button type="primary" size="default" @click="closeDialog()">关闭窗口</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
//引入微信扫码登录参数请求
import { reqWxLogin } from '@/api/hospital'

//引入倒计时组件
import CountDown from '../CountDown/index.vue'

import { ref, reactive, computed, watch } from 'vue'

//引入图标
import { User, Lock } from '@element-plus/icons-vue'

import type { WXLoginResponseData } from '@/api/hospital/type'

import { useRoute, useRouter } from 'vue-router'

//获取 user 仓库的数据（visiable）数据可以控制 login 组件的对话框的显示与隐藏
import useUserStore from '@/store/modules/user'
import { ElMessage } from 'element-plus'
let userStore = useUserStore()

//获取路由器对象
let $route = useRoute()
let $router = useRouter()

let scene = ref<number>(0) //0:手机号码登录；1:微信扫码登录
//点击微信扫描登录，微信小图标切换为微信扫码登录
const changeScene = async () => {
  //切换场景为1
  scene.value = 1
  //发请求获取微信扫码二维码需要的参数
  //咋们在向硅谷学校的服务器发请求，获取微信扫码登录页面参数
  //还需要携带一个参数：告诉学校服务器授权成功后以后重定向项目某一个页面
  let redirect_URL = encodeURIComponent(window.location.origin + '/wxlogin')
  let result: WXLoginResponseData = await reqWxLogin(redirect_URL)
  //生成微信扫描登录的二维码页面
  //@ts-ignore
  new WxLogin({
    self_redirect: true, //true:手机点击确认登录后可以在 iframe 内跳转到 redirect_uri
    id: 'login_container', //显示二维码容器 ID
    appid: result.data.appid, //应用的唯一标识 appid
    scope: 'snsapi_login', //代表微信扫描登录的页面已经授权了，应用授权的作用域
    redirect_uri: result.data.redirectUri, //填写授权回调域的路径，就是用户授权成功以后微信服务器向公司后台推送 code 地址
    state: result.data.state, //state 就学校服务器重定向地址，携带用户的信息
    style: 'black', //文字颜色
    href: '' //自定义样式链接
  })
}

//收集表单数据，收集手机号码
let loginParam = reactive({
  phone: '', //收集手机号码
  code: '' //收集对应的验证码
})
//计算出当前表单元素收集的内容是否是手机号码
let isPhone = computed(() => {
  //手机号码的正则表达式
  const reg = /^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\d{8}$/
  //返回相应的 boolean ，true:手机号码，false:不是手机号码
  return reg.test(loginParam.phone)
})

//定义一个响应式数据去控制倒计时组件的显示与隐藏
//flag，true:开始倒计时，false:并非倒计时
let flag = ref<boolean>(false)

//获取验证码按钮的回调
const getCode = async () => {
  //解决 element-plus 按钮禁用还能点击的问题
  if (!isPhone.value || flag.value) return

  //开启倒计时模式，倒计时组件显示出来
  flag.value = true
  console.log('flag.value: ', flag.value)

  try {
    //获取验证码成功
    //通知 Pinia 仓库存储验证码
    await userStore.getCode(loginParam.phone)
    loginParam.code = userStore.code
  } catch (error) {
    //获取验证码失败
    ElMessage({
      type: 'error',
      message: (error as Error).message
    })
  }
}

//获取 form 组件实例
let form = ref<any>()

//点击用户登录按钮的回调
const login = async () => {
  //保证表单校验的两项都符合条件
  await form.value.validate()

  //发起登录请求
  //登录请求成功，顶部组件需要展示用户名字，对话框关闭
  //登录请求失败，弹出对应登录失败的错误信息
  try {
    //用户登录成功
    await userStore.userLogin(loginParam)
    //关闭对话框
    userStore.visiable = false

    //获取 url 的 query 参数
    //存储登录前想去而被登录限制的 url
    let redirect = $route.query.redirect
    if (redirect) {
      $router.push(redirect as string)
    } else {
      $router.push('./home')
    }
  } catch (error) {
    ElMessage({
      type: 'error',
      message: (error as Error).message
    })
  }
}

//自定义校验规则：手机号码的自定义校验规则
//@ts-ignore
const validatorPhone = (rule: any, value: any, callback: any) => {
  //rule:表单校验规则对象
  //value:当前的文本内容
  //callback:回调函数
  //手机号码的正则表达式
  const reg = /^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\d{8}$/
  //返回相应的 boolean ，true:手机号码，false:不是手机号码
  if (reg.test(value)) {
    callback()
  } else {
    callback(new Error('请输入正确的手机号码'))
  }
}
//自定义校验规则：验证码的自定义校验规则
//@ts-ignore
const validatorCode = (rule: any, value: any, callback: any) => {
  //rule:表单校验规则对象
  //value:当前的文本内容
  //callback:回调函数
  //手机号码的正则表达式
  const reg = /^\d{6}$/
  //返回相应的 boolean ，true:匹配，false:不匹配
  if (reg.test(value)) {
    callback()
  } else {
    callback(new Error('请输入正确的验证码格式'))
  }
}

//表单校验的规则对象
const rules = {
  //手机号码验证规则
  //required:代表当前字段务必进行校验
  //message:代表校验错误的提示信息
  //trigger:代表表单校验触发的时机，change:文本发生变化的时候校验，blur:失去焦点的时候校验
  //min:代表最小位数
  //max:代表最大位数
  // phone: [{required:true, message :'手机号码务必11位',trigger:'blur', min:11}],
  // code:[{required:true, message :'验证码务必6位',trigger:'blur',min:6}]
  phone: [{ trigger: 'change', validator: validatorPhone }],
  code: [{ trigger: 'change', validator: validatorCode }]
}

// //对话框关闭事件的回调
// const close = () => {
//     //清空收集的数据
//     Object.assign(loginParam,{phone:'',code:''});
//     //清除上一次校验的结果
//     form.value.resetFields();
// };

//关闭窗口的回调
const closeDialog = () => {
  userStore.visiable = false
  //close();
}

//点击手机短信验证码盒子的回调
const handler = () => {
  scene.value = 0
}

//监听场景的数据
watch(
  () => scene.value,
  (val: number) => {
    //说明是扫码
    if (val === 1) {
      userStore.queryState()
    }
  }
)
</script>

<script lang="ts">
export default {
  name: 'login'
}
</script>

<style scoped lang="scss">
.login_container {
  //深度选择器
  ::v-deep(.el-dialog__body) {
    border-top: 1px solid #ccc;
    border-bottom: 1px solid #ccc;
  }

  .login {
    padding: 20px;
    border: 1px solid #ccc;

    .webchat {
      display: flex;
      flex-direction: column;
      align-items: center;

      .phone {
        display: flex;
        flex-direction: column;
        align-items: center;
        p {
          margin: 10px 0;
        }
      }
    }
  }

  .bottom {
    display: flex;
    flex-direction: column;
    align-items: center;

    p {
      margin: 10px 0px;
    }
  }

  .leftContent {
    .top {
      display: flex;
      justify-content: space-around;

      .item {
        display: flex;
        flex-direction: column;
        align-items: center;

        img {
          width: 130px;
          height: 130px;
        }

        p {
          margin: 5px 0px;
        }
      }
    }
  }

  .tip {
    text-align: center;
    margin: 20px 0px;
    font-size: 20px;
    font-weight: 900;
  }
}
</style>
